# 使用蓝图对象
from flask import g

from . import new_blu
from flask import session, render_template, current_app, jsonify, request
# 导入User
from info.models import User
from  info.utils.response_code import RET
# 导入News
from info.models import News, Category
from info import constants
from  info.utils.commons import login_required


# 2---使用蓝图对象
@new_blu.route('/')
def index():
    """
    展示登陆信息（用户的登陆状态）：
    1. 尝试从redis中读取user_id
    2. 根据user_id查询数据库
    3. 判断查询数据
    4. 将查询到的信息返回给模板
    5. 展示用户信息

    :return:
    """
    # 从redis中获取user_id
    user_id = session.get('user_id')
    # 定义变量默认为None，用来保存查询结果
    user = None
    # 如果用户已登录
    if user_id:
        # 根据user_id来查询mysql数据库
        try:
            user = User.query.filter_by(id=user_id).first()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='查询数据失败')
        # 判断查询结果
        if not user:
            return jsonify(errno=RET.NODATA, errmsg='没有用户数据')

    # 展示新闻列表点击排行
    try:
        # 默认实现的是按照新闻点击次数进行查询，并且分页6条数据
        news_list = News.query.order_by(News.clicks.desc()).limit(6)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询新闻数据失败')
    # 判断查询结果是否有数据
    if not news_list:
        return jsonify(errno=RET.NODATA,errmsg='无新闻排行数据')
    # 如果有数据，定义容器来存储新闻数据
    new_dict_list = []
    # 遍历查询结果的对象
    for news in news_list:
        # 模型咧中定义的方法， 获取对象的数据， 类似于__repr__方法的作用
        new_dict_list.append(news.to_dict())

    # 展示项目首页分类数据
    try:
        categories =  Category.query.all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询分类数据失败')
    # 判断查询结果
    if not categories:
        return jsonify(errno=RET.NODATA, errmsg='无分类数据')
    # 定义容器，用来存储遍历的查询对象
    category_list = []
    for category in categories:
        category_list.append(category.to_dict())


    # 定义字典用来保存用户的基本信息，包括头像、昵称、手机号等
    # 如果用户已登录，调用模型类中to_dict方法，可以把查询的对象转成可读字符串，类似于__repr__方法
    # if user else None 三元表答式
    # 相当于：
    # if user:
    #     return data
    # else:
    #     return None
    data = {
        "user_info":user.to_dict() if user else None,
        "news_dict_list":new_dict_list,
        "category_list": category_list
    }

    return render_template('news/index.html', data=data)

@new_blu.route('/favicon.ico')
def favicon():
    # 应用上下文调用Flask内置的发送静态文件的方法，发送一个文件给浏览器
    return current_app.send_static_file('news/favicon.ico')

@new_blu.route('/news_list')
@login_required
def get_news_list():
    """
    首页新闻列表数据加载
    1.获取参数，args, cid新闻分类id， page页数、per_page每页数据条目
    var params = {
        ‘cid’ = 分类id
        ‘page’:page,
        'per_page':per_page
    }
    $.get(/news_list,parmams,function(resp))
    2.校验参数，把参数转成整型值
    3.查询数据库，根据分类id进行过滤查询，默认按照新闻发布时间进行排序，
    对排序结果进行分页paginate（page，每页条目数，False）
    4.分页查询返回的是分页对象
    paginate.items
    paginate.pages
    paginate.page
    5. 遍历分页后的数据，调用模型类中的方法，获取分页后的新闻数据
    6. 返回结果
    :return:
    """
    # 获取get请求的查询字符串，新闻分类id
    cid = request.args.get('cid','1')
    page = request.args.get('page','1')
    per_page = request.args.get('per_page','10')
    print(cid)
    # 检查参数，把参数转成int类型
    try:
        cid,page,per_page = int(cid),int(page),int(per_page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='参数类型错误')
    # 根据分类id进行查询
    # 定义变量，存储过滤条件
    filters = []
    # 判断分类id必须大于1
    if cid > 1:
        filters.append(News.category_id == cid)
    try:
    # 默认按照分类id进行过滤，其次按照新闻发布时间进行排序，paginate分页参数1为页数，参数2每页的数目，参数3分页异常不报错
        paginate = News.query.filter(*filters).order_by(News.create_time.desc()).paginate(page,constants.HOME_PAGE_MAX_NEWS,False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询列表新闻数据失败')
    # 获取分页后的新闻数据模型对象/总页数/当前页数
    news_list = paginate.items
    total_page = paginate.pages
    current_page = paginate.page
    # 遍历分页后的对象
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_dict())

    # 返回数据
    data = {
        "news_dict_list": news_dict_list,
        "total_page": total_page,
        "current_page": current_page
    }

    return jsonify(errno=RET.OK,errmsg='OK',data=data)

@new_blu.route('/<int:news_id>')
@login_required
def get_news_detail(news_id):
    """
    新闻详情页面：
    1、获取信息id
    2、根据新闻id来查询数据库
    3、校验查询结果
    4、返回新闻的数据，to_dict()
    :param news_id:
    :return:
    """
    # 根据新闻id查询数据库
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询新闻详情数据失败')
    # 检查查询结果
    if not news:
        return jsonify(errno=RET.NODATA, errmsg='无新闻数据')
    # 展示项目首页分类数据
    try:
        categories = Category.query.all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询分类数据失败')
    # 判断查询结果
    if not categories:
        return jsonify(errno=RET.NODATA, errmsg='无分类数据')
    # 定义容器，用来存储遍历的查询对象
    # category_list = []
    # for category in categories:
    #     category_list.append((category.to_dict))

    data = {
        "news":news.to_dict()
        # "category_list": category_list
    }
    # 调用模板页面返回数据
    return render_template('news/detail.html', data=data)

@new_blu.route('/news_collect',methods=['POST'])
@login_required
def news_collect():
    """
    收藏或取消收藏
    1、尝试获取用户信息
    2、获取参数news_id,action
    3、检查news_id必须为整型值
    4、检查action参数必须为collect/cancel_collect;;;;'collect', 'cancel_collect'
    5、查询新闻数据，确认新闻的存在
    6、校验查询结果
    7、判断用户选择的是收藏还是取消收藏
    收藏：user.collection_news.append(news)
    取消：user.collection.remove(news)
    8、返回结果

    :return:
    """
    # 获取用户信息
    user = g.user
    # 判断用户是否登录
    if not user:
        return jsonify(errno=RET.SESSIONERR,errmsg='用户未登录')
    # 获取参数
    news_id = request.json.get('news_id')
    action = request.json.get('action')
    # 对news_id进行强转成int
    try:
        print(news_id)
        news_id = int(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg='参数格式错误')
    # 对action行为进行检查
    if action not in['collect', 'cancel_collect']:
        return jsonify(errno=RET.PARAMERR,errmsg='参数错误')
    # 根据news_id查询数据库
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询数据失败')
    # 检查查询结果
    if not news:
        return jsonify(errno=RET.NODATA,errmsg='无新闻数据')
    # 判断用户选择是收藏还是取消收藏
    if action == 'collect':
        # 判断用户是否收藏过
        if news not in user.collection_news:
            user.collection_news.append(news)
    else:
        user.collection_news.remove(news)

    return jsonify(errno=RET.OK,errmsg='OK')